import { Injectable } from '@nestjs/common';
import {
  ValidationArguments,
  ValidationOptions,
  ValidatorConstraint,
  ValidatorConstraintInterface,
  registerDecorator,
} from 'class-validator';
import { DataSource, ObjectType, Repository, Entity } from 'typeorm';

type Condition = {
  entity: ObjectType<any>;
  /**
   * 用于查询的比对字段,默认id
   */
  property?: string;
};

@ValidatorConstraint({ name: 'IsUniqueName', async: true })
@Injectable()
export class UniqueValidate implements ValidatorConstraintInterface {
  constructor(private readonly dataSource: DataSource) {}
  async validate(value: string, args?: ValidationArguments): Promise<boolean> {
    const config: Omit<Condition, 'entity'> = {
      property: args.property,
    };
    if (!args.constraints[0].entity) return false;
    const obj: Condition = {
      ...config,
      ...args.constraints[0],
    };
    const reop = this.dataSource.getRepository(obj.entity);
    const res = await reop.findOne({
      where: {
        [obj.property]: value,
      },
    });

    return !res;
  }
  defaultMessage(args: ValidationArguments) {
    const { entity, property } = args.constraints[0];
    const queryProperty = property ?? args.property;
    if (!(args.object as any).getManager) {
      return 'getManager function not been found!';
    }
    if (!args.object) return 'Model not been specified!';

    return `${queryProperty} of ${entity.name} must been unique!`;
  }
}
export function IsUnique(
  entity: Condition | ObjectType<any>,
  validationOptions?: ValidationOptions,
) {
  return (object: Record<string, any>, propertyName: string) => {
    registerDecorator({
      target: object.constructor,
      propertyName,
      options: validationOptions,
      constraints: [entity],
      validator: UniqueValidate,
    });
  };
}
